﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Reflection;
using System.ComponentModel;
using System.Security;
using System.Security.Permissions;

using PickGold.Util;

namespace PickGold.Web.Controls
{
	/// <summary>
	/// Enum 数据源。
	/// </summary>
	[ControlBuilder(typeof(Builder))]
	[ToolboxData("<{0}:EnumDataSource runat=\"server\" />")]
	[ParseChildren(true)]
	[PersistChildren(false)]
	public class EnumDataSource : DataSourceControl
	{
		class V : DataSourceView
		{
			public V(EnumDataSource source) : base(source, string.Empty)
			{
				this.Source = source;
			}

			protected override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments)
			{
				if (this.Source == null)
					return null;

				var c = new int[1];
				var e = EnumDataSource.ExecuteSelect(this.Source.E, this.Source.C, this.Source.N, arguments.StartRowIndex, arguments.MaximumRows, c);
				arguments.TotalRowCount = c[0];
				return e;
			}

			/// <summary>
			/// EnumDataSource
			/// </summary>
			public EnumDataSource Source;
		}

		/// <summary>
		/// Enum Type
		/// </summary>
		[Bindable(true)]
		[DisplayName("Enum Type")]
		[Description("Enum Type")]
		public string EnumType
		{
			set
			{
				if (string.IsNullOrWhiteSpace(value))
				{
					this.E = null;
					return;
				}

				var t = Type.GetType(value, true, true);
				if (t.IsEnum)
				{
					this.E = t;
					return;
				}

				throw new ArgumentOutOfRangeException();
			}
			get
			{
				if (this.E == null)
					return null;

				return this.E.AssemblyQualifiedName;
			}
		}

		/// <summary>
		/// 分类过滤，只显示指定分类[Category(Category)]的成员
		/// </summary>
		[Bindable(true)]
		[DisplayName("Enum Type")]
		[Description("Enum Type")]
		[TypeConverter(typeof(StringArrayConverter))]
		public string[] Categories
		{
			set
			{
				this.C = value;
			}
			get
			{
				return this.C;
			}
		}

		/// <summary>
		/// Return Name
		/// </summary>
		[Bindable(true)]
		[DisplayName("Return Name")]
		[Description("Return Name")]
		public bool ReturnName
		{
			set
			{
				this.N = value;
			}
			get
			{
				return this.N;
			}
		}

		/// <summary>
		/// 获取与数据源控件关联的命名的数据源视图。
		/// </summary>
		/// <param name="viewName">要检索的 System.Web.UI.DataSourceView 的名称。在只支持一个视图的数据源控件（如 System.Web.UI.WebControls.SqlDataSource）中，此参数会被忽略。</param>
		/// <returns>返回与 System.Web.UI.DataSourceControl 关联的指定 System.Web.UI.DataSourceView。</returns>
		protected override DataSourceView GetView(string viewName)
		{
			return new V(this);
		}

		/// <summary>
		/// 返回枚举成员列表
		/// </summary>
		/// <param name="type">枚举类型</param>
		/// <param name="categories">分类过滤</param>
		/// <param name="name">返回名称</param>
		/// <param name="index">开始索引</param>
		/// <param name="length">最多返回数量</param>
		/// <param name="count">使用首个元素返回元素总数</param>
		/// <returns>枚举成员列表</returns>
		public static IEnumerable ExecuteSelect(Type type, string[] categories, bool name, int index, int length, int[] count)
		{
			if (type == null || !type.IsEnum)
				yield break;

			if (categories == null || categories.Length == 0)
			{
				var v = name ? Enum.GetNames(type) : Enum.GetValues(type);
				if (length <= 0 || length + index > v.Length)
					length = v.Length;
				for (; index < length; index++)
					yield return v.GetValue(index);
				if (count != null && count.Length > 0)
					count[0] = v.Length;
				count = null;
				yield break;
			}

			var f = type.GetFields(BindingFlags.Public | BindingFlags.Static);
			var l = f.Length;
			var t = 0;
			var a = 0;
			foreach (var cc in categories)
			{
				if (cc == AsciiString.ASTERISK || cc == AsciiString.EXCLAMATION)
					a++;
			}
			foreach(var ff in f)
			{
				var c = string.Empty;
				var cs = ff.GetCustomAttributes(typeof(CategoryAttribute), true) as CategoryAttribute[];
				if (cs != null && cs.Length > 0)
					c = cs[0].Category ?? string.Empty;
				foreach (var cc in categories)
				{
					if ((c == string.Empty && string.IsNullOrWhiteSpace(cc)) ||
						(c != string.Empty && !string.IsNullOrWhiteSpace(cc) && c.IndexOf(cc, StringComparison.OrdinalIgnoreCase) >= 0))
					{
						c = null;
						if (a > 0)
							break;

						if (t >= index && (t < length || length <= 0))
						{
							if (name)
								yield return ff.Name;
							else
								yield return ff.GetValue(null);
						}
						t++;
						break;
					}
				}
				if (c == null || a == 0)
					continue;

				if (t >= index && (t < length || length <= 0))
				{
					if (name)
						yield return ff.Name;
					else
						yield return ff.GetValue(null);
				}
				t++;
			}
			if (count != null && count.Length > 0)
				count[0] = t;
			count = null;
		}

		private Type E;
		private bool N;
		private string[] C;
	}//class
}//namespace
